package its_models.expert_model.expert_help_util;

import sudoku_properties.BasicSudokuParam ;

public class SudokuCoordinate {
    
    public SudokuCoordinate(){}

    public SudokuCoordinate( int cellPosX, int cellPosY ) {
        this.setCellPosition( cellPosX, cellPosY ) ; 
    }

    public void copy( SudokuCoordinate copySudokuCoordinate){
        this.columnIndex = copySudokuCoordinate.getColumnIndex() ;
        this.rowIndex = copySudokuCoordinate.getRowIndex() ;
        this.boxIndex = copySudokuCoordinate.getBoxIndex() ;
    }

    
    /* set the position of cells in terms of column, row and vbox index */
    /* input cell position X and Y is from position 0,0 to 8,8*/
    public void setCellPosition( int inputCellIndexX, int inputCellIndexY ) {
        
        final int cellIndexX = inputCellIndexX;
        final int cellIndexY = inputCellIndexY;         
        /* Step 1 : Calculate Column Index */
        columnIndex = cellIndexX ;
        /* Step 2 : Calculate Row Index */
        rowIndex = cellIndexY ;
                
        /* Step 3 : Calculate Box Index */
        boxIndex = ((( (int) Math.ceil( Math.rint(cellIndexY+1) / BOX_LENGTH_IN_CELLS) ) * BOX_LENGTH_IN_CELLS)+
                ( (int) Math.floor( Math.rint(cellIndexX) / BOX_LENGTH_IN_CELLS) )) - 2 ;
        --boxIndex; 
    }
    
    /* get cell index */
    public int getColumnIndex(){
        return columnIndex ;
    }  
    public int getRowIndex(){
        return rowIndex ;
    }
    public int getBoxIndex(){
        return boxIndex ;
    }
    
    /* get all coordinate in a column */
    public int[][] getSameColumnCoordinates(){
        
        int[][] sameColCoordinates = new int[NUM_CELLS_IN_UNIT][NUM_COORDINATES] ;
        
        for( int i=0 ; i< sameColCoordinates.length ; i++ ){
            sameColCoordinates[i][COLUMN_INDICATOR] = columnIndex ;
            sameColCoordinates[i][ROW_INDICATOR] = i;
        }
        return sameColCoordinates ;
    }

    /* get all coordinate in a row */
    public int[][] getSameRowCoordinates(){
        int[][] sameRowCoordinates = new int[NUM_CELLS_IN_UNIT][NUM_COORDINATES] ;
        
        for( int i=0 ; i < sameRowCoordinates.length ; i++ ){
            sameRowCoordinates[i][COLUMN_INDICATOR] = i;
            sameRowCoordinates[i][ROW_INDICATOR] = rowIndex;
        }
        return sameRowCoordinates ;
    }
    
    /**
     * Method to get Int coordinates that belong to the same Box of this cell.
     *
     *  @return int[][] the coordinates of the cell int the same box
     *                  *where the first index is the Column Index, 
     *                   while the second is the Row Index
     */
    public int[][] getSameBoxCoordinates(){
        final int COL_START_POS = ( (int) Math.floor(Math.rint( columnIndex ) / BOX_LENGTH_IN_CELLS) ) * BOX_LENGTH_IN_CELLS;
        final int ROW_START_POS = ( (int) Math.floor(Math.rint( rowIndex ) / BOX_LENGTH_IN_CELLS) ) * BOX_LENGTH_IN_CELLS;
        int[][] sameBoxCoordinates = new int[NUM_CELLS_IN_UNIT][NUM_COORDINATES];
        
        for( int i = 0 ; i < BOX_LENGTH_IN_CELLS ; i++)
        {
            for( int j = 0 ; j < BOX_LENGTH_IN_CELLS ; j++ )
            {
                final int ELEMENT_POSITION = ( i* BOX_LENGTH_IN_CELLS ) + j ;
                for( int k=0 ; k<sameBoxCoordinates[ELEMENT_POSITION].length ;
                     k++)
                {
                    if( k==COLUMN_INDICATOR )
                    {
                        sameBoxCoordinates[ELEMENT_POSITION][k] = COL_START_POS + j;
                    }
                    else if( k==ROW_INDICATOR )
                    {
                        sameBoxCoordinates[ELEMENT_POSITION][k] = ROW_START_POS + i;
                    }
                }
            }
        }
        return sameBoxCoordinates ;
    }
    
    /* comparsion between coordinates */
    public boolean isThisLessThan( SudokuCoordinate inputObject ){
        boolean isThisLess = false ; 
        
        if( (this.getColumnIndex() < inputObject.getColumnIndex()) &&
            (this.getRowIndex() < inputObject.getRowIndex()) ){
            isThisLess = true ;
        }        
        return isThisLess ;
    }
    public boolean isAtSamePositionAs( SudokuCoordinate inputObject )
    {
        boolean isSamePosition = false ; 
        
        if( (this.getColumnIndex() == inputObject.getColumnIndex()) &&
            (this.getRowIndex() == inputObject.getRowIndex()) )
        {
            isSamePosition = true ;
        }
        return isSamePosition ;
    }

    public boolean equal(SudokuCoordinate inputCoordinate ){
        boolean isEqual = false ;

        if( (this.getColumnIndex() ==inputCoordinate.getColumnIndex()) &&
            (this.getRowIndex() == inputCoordinate.getRowIndex()) &&
            (this.getBoxIndex() == inputCoordinate.getBoxIndex()) ){

            isEqual = true ;
        }
        return isEqual ;
    }

    /* the index of the row that this cell belong to */ 
    private int rowIndex ; 
    /* the index of the column that this cell belong to */ 
    private int columnIndex ; 
    /* the index of the box that this cell belong to */ 
    private int boxIndex ; 
    /* Indicator for reference : [x][y][z]  x stands for column, y stands for row, z stands for box */ 
    public final static int COLUMN_INDICATOR = 1 ;
    public final static int ROW_INDICATOR = 0 ;
    public final static int BOX_INDICATOR = 2 ; 
    /* constand variables */
    /* BasicSudokuParam */
    final static int NUM_CELLS_IN_UNIT = BasicSudokuParam.getNumCellsInUnit() ;
    final static int BOX_LENGTH_IN_CELLS = BasicSudokuParam.getBoxLengthInCells() ; 
    /* Only in this class */
    /* number of coordinates : x cor and Y cor, thereby =2 */
    final int NUM_COORDINATES = 2; 
}
